#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

struct Goods
{
	string _name;
	double _price;
	int _evaluate;
	//.....

	Goods(const char* str, double price, int evaluate)
		:_name(str)
		,_price(price)
		,_evaluate(evaluate)
	{}

};

struct ComparePriceLess
{
	bool operator()(const Goods& gl, const Goods& gr)
	{
		return gl._price < gr._price;
	}
};

struct ComparePriceGreater
{
	bool operator()(const Goods& gl, const Goods& gr)
	{
		return  gl._price > gr._price;
	}
};

//int main()
//{
//	vector<Goods> v = { { "苹果", 2.1, 5 }, { "香蕉", 3, 4 }, 
//                        { "橙子", 2.2,3 }, { "菠萝", 1.5, 4 } };
//
//	sort(v.begin(), v.end(), ComparePriceLess());
//	sort(v.begin(), v.end(), ComparePriceGreater());
//
//	//价格升序
//	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2)
//		{
//			return g1._price < g2._price;
//		});
//
//	//返回值类型：bool
//	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2)-> bool
//		{
//			return g1._price < g2._price;
//		});
//
//	
//	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2)
//		{
//			return g1._evaluate < g2._evaluate;
//		});
//
//
//	return 0;
//}

 //                       捕捉列表       参数                   返回值           函数体
//lambda表达式书写格式：[capture-list] (parameters) mutable -> return-type { statement }


//int main()
//{
//	auto add1 = [](int x, int y)->int {return x + y; };
//	cout << add1(1, 2) << endl;
//
//	auto func1 = []()->int 
//	{
//			cout << "hello xlf" << endl;
//			cout << "hello world" << endl;
//			return 0;
//	};
//
//	func1();
//
//	//返回值类型可自动推到，所以可以省略
//	//无参数可以省略
//	auto func2 = []
//		{
//			cout << "hello xlf" << endl;
//			cout << "hello world" << endl;
//			return 0;//有返回值可以省略返回类型
//		};
//
//	cout << func2() << endl;
//
//	return 0;
//}


//int main()
//{
//	int a = 0, b = 1;
//	auto swap1 = [](int& x, int& y)
//		{
//			//只能用当前lambda局部域和捕捉的对象
//			int temp = x;
//			x = y;
//			y = temp;
//		};
//
//	swap1(a, b);
//
//	// 捕捉列表
//	// 传值捕捉本质是一种拷贝，并且const修饰了
//	// mutable相当于去掉const属性，可以修改了
//	// 但是修改了不会影响外面被捕捉的值，因为只是外面变量的一种拷贝
//	auto swap2 = [a, b]() mutable//传值（const）捕捉的值是不能改变的
//		{
//			int temp = a;
//			a = b;
//			b = temp;
//		};
//
//	swap2();
//
//	auto swap2 = [&a, &b]() //引用捕捉（不是const，是别名）
//		{
//			int temp = a;
//			a = b;
//			b = temp;
//		};
//
//	return 0;
//}


//int x = 0;//全局
//int main()
//{
//	//只能用当前lambda局部域和捕捉的对象和全局对象
//
//	int a = 0, b = 1, c = 2, d = 3;
//	//所有值传值捕捉
//	auto func1 = [=]
//		{
//			int ret = a + b + c + d;
//			return ret;
//		};
//
//	//所有值引用捕捉
//	auto func1 = [&]
//		{
//			a++;
//			b++;
//			c++;
//			d++;
//			int ret = a + b + c + d + x;//全局的x也可以用
//			return ret;
//		};
//
//	//混合捕捉1
//	auto func1 = [&a, b]// a 传引用捕捉， b 传值（const）捕捉（b 不能修改，加mutable可修改）
//		{
//			a++;
//			//b++;
//			int ret = a + b ;
//			return ret;
//		};
//
//
//	//混合捕捉2
//	//所有值以引用方式捕捉，d用传值捕捉
//	auto func1 = [& , d]
//		{
//			a++;
//			b++;
//			c++;
//			//d++;
//			int ret = a + b + c + d;
//			return ret;
//		};
//
//	// 注意：
//	// mutable虽然可以去掉const属性，可以修改函数体里面的变量，但是一般不用
//	// 因为怕误用，怕有一些人认为修改了lambda函数体里面的变量，就可以影响外面的
//	// 其实是不影响外面的。
//
//
//
//	//混合捕捉3
//	//所有值以传值方式捕捉，d用引用捕捉
//	auto func1 = [= , &d]//如果用来lambda就表示在函数体里面 a b c 都先++了，
//		{                 //ret的值是a b c ++之后的值，但是里面abc对外面是没有影响的
//			//a++;        // &d 才对外面的 d 有影响
//			//b++;        // 所以 mutable 要慎用
//			//c++;
//			d++;
//			int ret = a + b + c + d;
//			return ret;
//		};
//
//	return 0;
//}


// lambda 匿名函数对象
// 捕捉列表的对象是成员变量存在lambda类对象中
// 捕捉的本质是构造函数的初始化参数

//class Rate
//{
//public:
//	Rate(double rate) : _rate(rate)
//	{}
//	double operator()(double money, int year)
//	{
//		return money * _rate * year;
//	}
//private:
//	double _rate;
//};
//
//int main()
//{
//	// 函数对象
//	double rate = 0.015;
//	Rate r1(rate);
//	r1(10000, 2);
//
//	// lamber
//	auto r2 = [=](double monty, int year)->double 
//		{
//			return monty * rate * year;
//		};
//	
//	
//	auto r3 = [=](double monty, int year)->double 
//		{
//			return monty * rate * year;
//		};
//
//	r2(10000, 2);
//	return 0;
//}


////////////////////////////////////////////////////////////////
//#include<functional>
//// function: 对可调用对象进行包装
////包装器：可进行类型统一
////返回值和参数是相同的
//
//int f(int a, int b)
//{
//	return a + b;
//}
//
//struct Functor
//{
//public:
//	int operator()(int a, int b)
//	{
//		return a + b;
//	}
//};
//
//class Plus
//{
//public:
//	static int plusi(int a, int b)
//	{
//		return a + b;
//	}
//
//	//含有隐藏的this
//	double plusd(double a, double b)
//	{
//		return a + b;
//	}
//};
//
//int main()
//{
//	//包装可调用对象
//	function<int(int, int)> f1 = f;//函数指针
//	function<int(int, int)> f2 = Functor();//仿函数对象
//	function<int(int, int)> f3 = [](int a, int b) {return a + b; };//lambda
//
//	cout << f1(1, 1) << endl;
//	cout << f2(1, 1) << endl;
//	cout << f3(1, 1) << endl;
//
//	//语法规定：
//	//非静态的成员函数，成员函数要取函数指针时，要加 & 符号
//
//	//包装静态成员函数
//	function<int(int, int)> f4 = &Plus::plusi;//成员函数的函数名受类域的限制
//	cout << f4(1, 1) << endl;
//
//	//包装非静态成员函数
//	//Plus* 隐含的this
//	function<double(Plus*, double, double)> f5 = &Plus::plusd;
//	Plus pd;
//	cout << f5(&pd, 1.1, 1.1) << endl;//传指针
//
//	function<double(Plus, double, double)> f6 = &Plus::plusd;
//	cout << f6(pd, 1.1, 1.1) << endl;//传有名对象
//	cout << f6(Plus(), 1.1, 1.1) << endl;//传匿名对象
//
//	// Plus* 和 Plus 为什么都可以？ 
//	// function的本质：（不是直接传参，而是转换成指针之后，取调对应的函数）
//	// 接收到函数指针（plusd）以后，
//	// function里面作为类似成员变量的方式，把函数指针存起来
//	// 存起来了以后，f6(pd, 1.1, 1.1) 调用的是operater()，
//	// operater()再来调用对应的可调用对象
//	// 可调用对象里面又去调用 &Plus::plusd 这个函数 
//
//
//	return 0;
//}

////////////////////////////////////////////////////////////////////////
#include<functional>
// bind绑定：对可调用对象调整（顺序、个数）参数
// 可调用对象：函数指针、lambda、仿函数
// 绑定看起来没有返回值，实际上是有返回值的，
// 它会返回一个可调用对象（调整的参数对这个参数进行调整顺序、个数）
// bind 本质返回一个仿函数对象

int Sub(int a, int b)
{
	return (a - b) * 10;
}

int SubX(int a, int b, int c)
{
	return (a - b - c) * 10;
}

class Plus
{
public:
	static int plusi(int a, int b)
	{
		return a + b;
	}

	//含有隐藏的this
	double plusd(double a, double b)
	{
		return a + b;
	}
};

//placeholders命名空间的名字
//placeholders::_1  参数


using placeholders::_1;
using placeholders::_2;
using placeholders::_3;
//int main()
//{
//	//调整参数顺序
//	//auto sub1 = bind(Sub, placeholders::_1, placeholders::_2);
//	auto sub1 = bind(Sub, _1, _2);
//	cout << sub1(10, 5) << endl;
//
//	// 调整参数顺序
//	// _1代表第一个实参
//	// _2代表第二个实参
//	// ...
//	auto sub2 = bind(Sub, _2, _1);
//	cout << sub2(10, 5) << endl;
//
//	// 调整参数个数
//	auto sub3 = bind(Sub, 100, _1);
//	cout << sub3(5) << endl;
//
//	auto sub4 = bind(Sub, _1, 100);
//	cout << sub4(5) << endl;
//
//	auto sub5 = bind(SubX, 100, _1, _2);
//	cout << sub3(5, 1) << endl;
//	
//	auto sub6 = bind(SubX, _1, 100, _2);
//	cout << sub6(5, 1) << endl;
//
//	function<double(Plus, double, double)> f6 = &Plus::plusd;
//	Plus pd;
//	cout << f6(pd, 11, 1.1) << endl;
//	cout << f6(Plus(), 11, 1.1) << endl;
//
//	// bind 一般用于，绑死一些固定参数
//	//auto func1 = [](double rate, double monty, int year)->double {return monty * rate * year;};
//	auto func1 = [](double rate, double monty, int year)->double {
//		double ret = monty;
//		for (int i = 0; i < year; i++)
//		{
//			ret += ret * rate;
//		}
//
//		return ret - monty;
//		};
//
//	function<double(double)> func3_1_5 = bind(func1, 0.015, _1, 3);
//	function<double(double)> func5_1_5 = bind(func1, 0.015, _1, 5);
//	function<double(double)> func10_2_5 = bind(func1, 0.025, _1, 10);
//	function<double(double)> func20_3_5 = bind(func1, 0.035, _1, 30);
//
//	cout << func3_1_5(1000000) << endl;
//	cout << func5_1_5(1000000) << endl;
//	cout << func10_2_5(1000000) << endl;
//	cout << func20_3_5(1000000) << endl;
//
//	 
//
//	return 0;
//}

#define _CRT_SECURE_NO_WARNINGS 1
#include<map>
#include<string>

int main()
{
	int i = 10;
	auto p = &i;
	auto pf = strcpy;
	cout << typeid(p).name() << endl;
	cout << typeid(pf).name() << endl;
	map<string, string> dict = { {"sort", "排序"}, {"insert", "插入"} };
	//map<string, string>::iterator it = dict.begin();
	auto it = dict.begin();
	return 0;
}